﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once

#include "GcmpCommandAction.h"
#include "ElementId.h"
#include "PickNodeReferenceOption.h"

namespace gcmp
{
    class IUiView;
    class Vector3d;
    class IGraphicsNodeReference;
    class IPickFilter;
    class IAction;
    class IGraphicsElementShape;

    typedef std::vector<OwnerPtr<IGraphicsNodeReference>> GraphicsNodeReferenceOwnerPtrVector;

    /// \brief  拾取图形节点时使用的交换数据结构
    ///
    struct GCMP_COMMAND_ACTION_EXPORT PickNodeReferenceExchangeData
    {
        /// \brief 构造函数
        ///
        /// \param bSingleSelectModeInput 输入参数，表明是否单选
        /// \param pGNodeReferencesSelectionInput 输出参数，选择集
        /// \param pUserCancelledInput    输出参数，表明是否用户取消
        /// \param pMousePointInput 输出参数，鼠标点
        /// \param bMouseOnWorkPlaneInput 输入参数，表明鼠标是否应在工作平面上
        /// \param pPickedAuxiliaryElementIdInput 输出参数，若允许捕捉辅助对象，输出拾取到的辅助对象的Id
        PickNodeReferenceExchangeData(
            bool bSingleSelectModeInput,
            GraphicsNodeReferenceOwnerPtrVector* pGNodeReferencesSelectionInput,
            bool* pUserCancelledInput = nullptr,
            Vector3d* pMousePointInput = nullptr,
            bool bMouseOnWorkPlaneInput = false,
            ElementId* pPickedAuxiliaryElementIdInput = nullptr)
            : bSingleSelectMode(bSingleSelectModeInput)
            , pGNodeReferencesSelection(pGNodeReferencesSelectionInput)
            , pUserCancelled(pUserCancelledInput)
            , pMousePoint(pMousePointInput)
            , bMouseOnWorkPlane(bMouseOnWorkPlaneInput)
            , pPickedAuxiliaryElementId(pPickedAuxiliaryElementIdInput)
        {}

        /// 点选框选标志 true：点选，false：框选
        bool bSingleSelectMode;

        /// 选择集
        GraphicsNodeReferenceOwnerPtrVector* pGNodeReferencesSelection;

        /// 表明拾取操作是否被用户取消
        bool *pUserCancelled;

        /// 鼠标位置
        Vector3d* pMousePoint;

        /// 鼠标是否应在工作平面上
        bool bMouseOnWorkPlane;

        /// 拾取到的辅助对象的Id
        ElementId* pPickedAuxiliaryElementId;
    };

    /// \brief  拾取图形节点的Action类
    ///
    class GCMP_COMMAND_ACTION_EXPORT IPickNodeReferenceAction
    {
    public:

        /// \brief 创建移动回调函数
        ///
        /// \return 回调函数
        typedef std::function<void(IUiView* , const gcmp::Vector3d&)> MoveCallback;
        template<typename T>
        static MoveCallback CreateMoveCallback(void (T::*func)(IUiView*, const gcmp::Vector3d&), T* object)
        {
            return std::bind(func, object, std::placeholders::_1, std::placeholders::_2);
        }

        /// \brief 键盘按钮响应函数的回调函数
        /// \\ 返回值为ture，退出OnKeyDown； 返回值为false，继续执行OnKeyDown的默认行为
        /// \param nChar   键盘按钮
        /// \param pCurrentView    当前Ui视图
        /// \param mousePt   鼠标点
        typedef std::function<bool(int nChar, IUiView* pCurrentView, const gcmp::Vector3d& mousePt)> OnKeyDownCallback;

        /// \brief 创建键盘按钮响应函数的回调函数
        /// \param *func    T对象的函数指针
        /// \param object  T对象
        template<typename T>
        static OnKeyDownCallback CreateOnKeyDownCallback(
            bool (T::*func)(int nChar, IUiView* pCurrentView, const gcmp::Vector3d& mousePt), T* object)
        {
            if (object)
            {
                return std::bind(func, object, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
            }
            return nullptr;
        }

        /// \brief 创建拾取图形节点的Action类对象
        ///
        /// \param PickNodeReferenceExchangeData 拾取图形节点时使用的数据交换结构
        /// \param opPickFilter 图形节点类型过滤器
        /// \param cursorType 鼠标样式
        /// \param options 拾取设置
        /// \param isReturnKeyNeedCanceled   设置用户按了Enter和Retrun键是否退出，缺省不退出
        /// \return IAction接口
        static OwnerPtr<IAction> Create(
            PickNodeReferenceExchangeData& exchangeData,
            OwnerPtr<IPickFilter> opPickFilter,
            const PickNodeReferenceOption& options = PickNodeReferenceOption(),
            bool isReturnKeyNeedCanceled = false);

        /// \brief 创建拾取矩形选择框grep的回调函数
        /// \param pCurrentView 当前的UiView
        /// \param 起始点世界坐标 worldStart
        /// \param 终点世界坐标 worldEnd
        /// \return 返回创建的grep
        typedef std::function< OwnerPtr<IGraphicsElementShape> (const IUiView* pCurrentView, const gcmp::Vector3d& worldStart,const gcmp::Vector3d& worldEnd)> CreateSelectRectangleGrepCallback;

        /// \brief 设置拾取矩形选择框grep生成回调函数
        ///
        /// 生成的grep渲染层必须是GraphicsRenderLayer::TransientObject
        /// \param 拾取矩形选择框grep生成回调函数
        static void SetCreateSelectRectangleGrepCallback(CreateSelectRectangleGrepCallback callback);

        /// \brief 获得拾取矩形选择框grep生成回调函数
        /// \return 拾取矩形选择框grep生成回调函数
        static CreateSelectRectangleGrepCallback GetCreateSelectRectangleGrepCallback();
    };
}




